#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

#include <stdexcept>
#include <string>

#include "autocall-util.h"
#include "io-util.h"
#include "string-util.h"

using std::string;
using std::runtime_error;

void read(const char *file_name,string &buf)
{
    int core_ret;
    int fd = open(file_name,O_RDONLY);
    if (fd < 0)
        throw runtime_error(format("open(%s):%s",file_name,strerror(errno)));
    AUTOCALL_FUNC(closeFd) {
        if (fd >= 0)
            ::close(fd);
    };
    AUTOCALL(closeFd);

    struct stat file_stat;
    core_ret = fstat(fd,&file_stat);
    if(core_ret < 0)
        throw runtime_error(format("fstat(): %s",strerror(errno)));

    char *buf_ptr;
    int old_size;
    while (true) {
        old_size = buf.size();
        buf.resize(old_size+file_stat.st_blksize);
        buf_ptr = const_cast<char*>(buf.data()+old_size);
        core_ret = read(fd,buf_ptr,file_stat.st_blksize);
        if(core_ret < 0){
            if(errno == EINTR)
                continue;
            else
                throw runtime_error(format("read(%ld):%s",file_stat.st_blksize,strerror(errno)));
        }
        buf.resize(old_size+core_ret);
        if(core_ret == 0)
            break;
    }
    return ;
}

void write(const char *filename,const void *ptr,size_t size)
{
    int fd = open(filename,O_WRONLY|O_CREAT|O_TRUNC,0666);
    if (fd < 0)
        throw runtime_error(format("open(%s): %s",filename,strerror(errno)));
    AUTOCALL_FUNC(close_fd) {
        if (fd >= 0)
            close (fd);
    };
    AUTOCALL(close_fd);

    ssize_t write_ret = write(fd,ptr,size);
    if (write_ret == -1)
        throw runtime_error(format("write(%s,%zu): %s",filename,size,strerror(errno)));
    size_t writen_size = static_cast<size_t>(write_ret);
    if (writen_size != size)
        throw runtime_error(format("write(%s,%zu): %zu",filename,size,writen_size));

    return ;
}

